package com.lambo.maven.core.utils.superHttp.utils;

import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;

import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.NameValuePair;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.Credentials;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.HttpRequestRetryHandler;
import org.apache.http.client.config.AuthSchemes;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.AbstractExecutionAwareRequest;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpRequestBase;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.lambo.maven.core.utils.superHttp.SHttpException;
import com.lambo.maven.core.utils.superHttp.entity.SHttpConfig;

/**
 * SHttpUtil
 */
public class SHttpUtil {

    private static Logger logger = LoggerFactory.getLogger(SHttpUtil.class);

	public static int socketTimeout = 60000; 
	public static int connectTimeout = 60000;

    // 根据系统代理获取
    public static boolean isProxy() {
        return true;
    }

    public static void closeHttp(AbstractExecutionAwareRequest httpRequest, CloseableHttpResponse httpResponse) {
        try {
            httpRequest.abort();
            if(httpResponse != null) {
                httpResponse.close();
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
            logger.error("释放http连接异常");
        }
	}

    public static SSLConnectionSocketFactory getSslConent() {
        try {
            // 创建SSLContext对象，并使用我们指定的信任管理器初始化
            SSLContext sslContext = SSLContext.getInstance("SSL");
            sslContext.init(null, new TrustManager[]{
                //证书信任管理器（用于https请求）
                new X509TrustManager(){
                    @Override
                    public void checkClientTrusted(X509Certificate[] arg0,
                            String arg1) throws CertificateException {
                    }
                    @Override
                    public void checkServerTrusted(X509Certificate[] arg0,
                            String arg1) throws CertificateException {
                    }
                    @Override
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                }
            }, new SecureRandom());
                
            SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(
                sslContext, new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession sslSession) {
                        return true;
                    }
                });
            return sslsf;
        } catch(Exception e) {
            logger.error(e.getMessage(), e);
            throw new RuntimeException("获取sslContext异常");
        }
    }

    public static CloseableHttpClient getHttpClient(boolean isProxy, String host, Integer port) {
        return getHttpClient(isProxy, host, port, null);
    }

    public static CloseableHttpClient getHttpClient(boolean isProxy, String host, Integer port, SSLConnectionSocketFactory sslsf) {
        return getHttpClient(isProxy, host, port, "", "", sslsf);
    }

    private static CloseableHttpClient getHttpClient(SSLConnectionSocketFactory sslsf) {
        return getHttpClient(false, null, null, "", "", sslsf);
    }

    public static CloseableHttpClient getHttpClient() {
        return getHttpClient(false, null, null, "", "", null);
    }

    public static CloseableHttpClient getHttpClient(boolean isProxy, 
            String host, Integer port, String name, String pwd) {
        SSLConnectionSocketFactory sslsf = getSslConent();
        return getHttpClient(isProxy, host, port, name, pwd, sslsf);
    }

    // 根据系统参数获取 
    public static CloseableHttpClient getHttpClient(boolean isProxy, 
        String host, Integer port, String name, String pwd, SSLConnectionSocketFactory sslsf) {
        try {
            if(sslsf == null) {
                sslsf = getSslConent();
            }

            // 定义重发对象，重发次数为1
            HttpRequestRetryHandler retryHandler = new DefaultHttpRequestRetryHandler(1, true);

            if(isProxy) {

                logger.info("getHttpClient:使用代理");

                CredentialsProvider credsProvider = new BasicCredentialsProvider();
                AuthScope authScope = new AuthScope(host, port);
                Credentials credentials = new UsernamePasswordCredentials(name, pwd);
                credsProvider.setCredentials(authScope, credentials);
                // HttpHost proxy = new HttpHost(getProxyHost(), getProxyPort(), "http");
				CloseableHttpClient proxyHttpClient = HttpClients.custom()
                    .setSSLSocketFactory(sslsf)
                    .setDefaultCredentialsProvider(credsProvider)
                    .setRetryHandler(retryHandler)
                    .build();
    
                return proxyHttpClient;
            } else {
                CloseableHttpClient httpClient = HttpClients.custom()
                    .setRetryHandler(retryHandler)
                    .setSSLSocketFactory(sslsf)
                    .build();
                return httpClient;
            }

        } catch(Exception e) {
            logger.error(e.getMessage(), e);
            throw new RuntimeException("获取httpClient异常");
        }
    } 

    public static RequestConfig getRequestConfig() {
        return getRequestConfig(false, null, null);
    }

    public static RequestConfig getRequestConfig(boolean isProxy, String host, Integer port) {
        RequestConfig requestConfig;
        if(isProxy) {
            logger.info("代理配置：getRequestConfig");
            HttpHost proxy = new HttpHost(host, port, "http");
            requestConfig = RequestConfig.custom()
                .setProxy(proxy)
                .setProxyPreferredAuthSchemes(Arrays.asList(AuthSchemes.BASIC))	
                .setSocketTimeout(socketTimeout)
                .setConnectTimeout(connectTimeout)
                .setCookieSpec(CookieSpecs.STANDARD)
                .build();
        } else {
            requestConfig = RequestConfig.custom()
                .setSocketTimeout(socketTimeout)
                .setConnectTimeout(connectTimeout)
                .setCookieSpec(CookieSpecs.STANDARD)
                .build();
        }
        return requestConfig;
    }

    public static void initChrome(HttpRequestBase httpGet) {
		String chromeAgent = "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Mobile Safari/537.36";
		httpGet.addHeader("User-Agent", chromeAgent);
    }

	public static CloseableHttpClient getHttpClient(SHttpConfig config) {
		CloseableHttpClient proxyHttpClient;
		if(config.isNoneProxy()) {
            proxyHttpClient = SHttpUtil.getHttpClient(config.getSslsf()); 
            
        } else if(config.isCustomProxy() || config.isSystemProxy()) {
            String host = config.getProxyHost();
            Integer port = config.getProxyPort();
            String name = config.getUsername();
            String pwd = config.getPassword();
            // proxyHttpClient = HttpUtil.getHttpClient(true, host, port, config.getSslsf());
            proxyHttpClient = getHttpClient(true, host, port, name, pwd, config.getSslsf());
			
        } else if(config.isSock5Proxy()) { 
            // sock5代理实现的http对象
            proxyHttpClient = Sock5Util.getHttpClient(config.getSslsf());
            
        } else {
            return null;
        }
        return proxyHttpClient;
	}

    public static RequestConfig getRequestConfig(SHttpConfig config) {
		RequestConfig proxyRequestConfig;
		if(config.isNoneProxy()) {
            proxyRequestConfig = SHttpUtil.getRequestConfig();
        } else if(config.isCustomProxy() || config.isSystemProxy()) {
            String host = config.getProxyHost();
            Integer port = config.getProxyPort();
			proxyRequestConfig = SHttpUtil.getRequestConfig(true, host, port);
        } else if(config.isSock5Proxy()) { 
            // sock5代理实现的http对象
            proxyRequestConfig = SHttpUtil.getRequestConfig();
        } else {
            return null;
        }
        return proxyRequestConfig;
	}

    public static HttpEntity mapToEntity(Map<String, ?> param, String encoding) {
        try {
            List<NameValuePair> pairList = new ArrayList<NameValuePair>(); 
            for(Entry<String, ?> entry : param.entrySet()){
                pairList.add(new BasicNameValuePair(entry.getKey(), String.valueOf( entry.getValue()) ));
            }
            return new UrlEncodedFormEntity(pairList, encoding);
        } catch (Exception e) {
            throw new SHttpException("mapToEntity异常", e);
        }
    }
    
}